from google.appengine.api import users
from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.api import taskqueue
from google.appengine.ext.db import GqlQuery
import pickle

from random_file import *
import random

class WebUser(db.Model):
    name = db.StringProperty()
    city = db.StringProperty()
    state = db.StringProperty()
    sex = db.IntegerProperty() # 0:female, 1:male    

class LogAction(db.Model):
    user = db.ReferenceProperty(WebUser, collection_name='logs')
    action = db.IntegerProperty() # 0:click, 1:read, 2:change
    timespan = db.FloatProperty()
    sourceIp = db.IntegerProperty()

class Generator(webapp.RequestHandler):

    def post(self):             

        data_num = self.request.get('num')
        zipf_list_name = iniZif('zipf_int_' + data_num)
        zipf_list_timespan = iniZif('zipf_int_' + data_num + '_v2')
        zipf_list_city = iniZif('zipf_int_1000')
        city_num = len(zipf_list_city)
        zipf_list_state = iniZif('zipf_int_100')
        state_num = len(zipf_list_state)

	unique_user = set()
        user_key_dict = dict()
	user_list = []
	user_id_list = []
	for i in range(int(data_num)):
            userId = int(zipf_list_name[i])
            if userId not in unique_user:
		unique_user.add(userId)
                userName = 'user' + str(userId)
                city = 'city' + zipf_list_city[i%city_num]
                state = 'state' + zipf_list_state[i%state_num]
                sex = random.randint(0, 1)
		oneUser = WebUser(name=userName, city=city, state=state, sex=sex)
		user_list.append(oneUser)
		user_id_list.append(userId)
		# if there are 5000 users, batch put
		if(len(user_list) == 5000):
		    user_keys = db.put(user_list)
		    for j in range(5000):
			user_key_dict[user_id_list[j]] = user_keys[j]
		    user_keys, user_list, user_id_list = [], [], []
	if(len(user_list) > 0):
	    user_keys = db.put(user_list)
	    for j in range(len(user_list)):
		user_key_dict[user_id_list[j]] = user_keys[j]


	log_list = []	
	for i in range(int(data_num)):
	    userId = int(zipf_list_name[i])
	    user_key = user_key_dict[userId]
	    action = random.randint(0, 2)
            timespan = float(zipf_list_timespan[i])*1.28
            # ipAddr is choosen from the five ips of a given user
            ipaddrs = [(userId<<16)%(2**32), (userId<<17)%(2**32), (userId<<18)%(2**32), (userId<<19)%(2**32), (userId<<20)%(2**32)]
            actionLog = LogAction(user=user_key, action=action, timespan=timespan, sourceIp=ipaddrs[random.randint(0,4)])
            log_list.append(actionLog)
	    if(len(log_list) == 5000):
		db.put(log_list)
		log_list = []
	if(len(log_list) >0 ):
	    db.put(log_list)
	 
	
	''' inefficient put
	unique_user = set()

        for i in range(int(data_num)):
            userId = int(zipf_list_name[i])
            oneUser = WebUser()
            if userId not in unique_user:
                unique_user.add(userId)
                userName = 'user' + str(userId)
                city = 'city' + zipf_list_city[i%city_num]
                state = 'state' + zipf_list_state[i%state_num]
                sex = random.randint(0, 1)
                oneUser.name=userName
                oneUser.city=city
                oneUser.state=state
                oneUser.sex=sex
                oneUser.put()
            else:
                query = GqlQuery("select * from WebUser where name = :1", 'user' + str(userId))
                oneUser = query.get()
            action = random.randint(0, 2)
            timespan = float(zipf_list_timespan[i])*1.28
            # ipAddr is choosen from the five ips of a given user
            ipaddrs = [(userId<<16)%(2**32), (userId<<17)%(2**32), (userId<<18)%(2**32), (userId<<19)%(2**32), (userId<<20)%(2**32)]
            actionLog = LogAction(user=oneUser, action=action, timespan=timespan, sourceIp=ipaddrs[random.randint(0,4)])
            actionLog.put()
	    '''

class UserGenerator(webapp.RequestHandler):
    def post(self):
	num = self.request.get('num')
        offset = self.request.get('offset')
        taskqueue.add(url='/useGenerateTask', params={'num': num, 'offset':offset})
        self.redirect('/')


class UserGeneratorTask(webapp.RequestHandler):

    def post(self):
        data_num = self.request.get('num')
	offset = self.request.get('offset')
        zipf_list_name = iniZif('zipf_int_' + data_num + 'uni')
        zipf_list_city = iniZif('zipf_int_1000')
        city_num = len(zipf_list_city)
        zipf_list_state = iniZif('zipf_int_100')
        state_num = len(zipf_list_state)

        user_key_dict = dict()
        user_list = []
        user_id_list = []
	i = int(offset)
	end = i + 5000
        while (i < len(zipf_list_name)) and (i < end):
            userId = int(zipf_list_name[i])
            userName = 'user' + str(userId)
            city = 'city' + zipf_list_city[i%city_num]
            state = 'state' + zipf_list_state[i%state_num]
            sex = random.randint(0, 1)
            oneUser = WebUser(name=userName, city=city, state=state, sex=sex)
            user_list.append(oneUser)
            user_id_list.append(userId)
            # if there are 5000 users, batch put
            if(len(user_list) == 2000):
                user_keys = db.put(user_list)
                for j in range(2000):
                    user_key_dict[user_id_list[j]] = user_keys[j]
                user_keys, user_list, user_id_list = [], [], []
	    i += 1
        if(len(user_list) > 0):
            user_keys = db.put(user_list)
            for j in range(len(user_list)):
                user_key_dict[user_id_list[j]] = user_keys[j]


class LogGenerator(webapp.RequestHandler):
    def post(self):
        num = self.request.get('num')
        offset = self.request.get('offset')
        taskqueue.add(url='/logGenerateTask', params={'num': num, 'offset':offset})
        self.redirect('/')

class LogGeneratorTask(webapp.RequestHandler):

    def post(self):
        data_num = self.request.get('num')
        offset = self.request.get('offset')
	zipf_list_name = iniZif('zipf_int_' + data_num)
        zipf_list_timespan = iniZif('zipf_int_' + data_num + '_v2')

	query = db.GqlQuery('select * from WebUser')
	user_dict = dict()
	while True:
            results = query.fetch(2000)
            for item in results:
		id = item.name[4:]
		user_dict[id] = item.key()
            if len(results) < 2000:
                break
            cursor = query.cursor()
            query.with_cursor(cursor)

        user_id_list = []   
        log_list = []
	i = int(offset)
	end = i + 5000
        while i < int(data_num) and i < end:
            userId = int(zipf_list_name[i])
            user_key = user_dict[str(userId)]
            action = random.randint(0, 2)
            timespan = float(zipf_list_timespan[i])*1.28
            # ipAddr is choosen from the five ips of a given user
            ipaddrs = [(userId<<16)%(2**32), (userId<<17)%(2**32), (userId<<18)%(2**32), (userId<<19)%(2**32), (userId<<20)%(2**32)]
            actionLog = LogAction(user=user_key, action=action, timespan=timespan, sourceIp=ipaddrs[random.randint(0,4)])
            log_list.append(actionLog)
	    if(len(log_list) == 2000):
                db.put(log_list)
                log_list = []
	    i += 1
        if(len(log_list) >0 ):
            db.put(log_list)
